/*
 * Copyright (c) 2017-2019, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2019/08/21
 *
 * History:
 *
 */

#ifndef __LIND_COMPONENT_H__
#define __LIND_COMPONENT_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "osal_types.h"

#define AV_TRUE     1
#define AV_FLASE    0

typedef enum {
    AVERR_OK                = 0,
    AVERR_FAILED            = -1,
    AVERR_INVALID_ARGV      = -2,
    AVERR_NOMEM             = -3,
    AVERR_TIMEOUT           = -4,
    AVERR_AGAIN             = -5,
    AVERR_EOF               = -6,
    AVERR_NO_STREAM         = -7,
    AVERR_NO_VIDEO_STREAM   = -8,
    AVERR_NO_AUDIO_STREAM   = -9,
    AVERR_OPEN_FILE         = -10,
} av_error_e;

typedef enum _av_format_e
{
    AVFRAME_FORMAT_UNKNOWN  = -1,

    /*
     * video frame format define
     */
    VFRAME_FORMAT_RAW_NV21  = 0,
    VFRAME_FORMAT_RAW_YV12  = 1,
    VFRAME_FORMAT_SPSPPS    = 2,
    VFRAME_FORMAT_ES_H264   = 3,
    VFRAME_FORMAT_ES_H264_I = 4,
    VFRAME_FORMAT_ES_H265   = 5,
    VFRAME_FORMAT_ES_H265_I = 6,

    /*
     * audio frame format define
     */
    AFRAME_FORMAT_RAW_PCM   = 100,
    AFRAME_FORMAT_ES,

    /*
     * extend format for x264 encode
     */
    VFRAME_FORMAT_RAW_BRGA  = 1000
} av_format_e;

typedef enum _av_enc_type_t
{
    AV_ENC_TYPE_UNKNOWN     = -1,

    AV_ENC_TYPE_H264        = 1,
    AV_ENC_TYPE_H265        = 2,
    AV_ENC_TYPE_JPEG        = 3,

    AV_ENC_TYPE_PCM         = 100,
    AV_ENC_TYPE_MP3         = 101,
    AV_ENC_TYPE_MP2         = 102,
    AV_ENC_TYPE_AAC         = 103,
    AV_ENC_TYPE_G726        = 104,
    AV_ENC_TYPE_OPUS        = 105,
    AV_ENC_TYPE_AMR_NB      = 106,
    AV_ENC_TYPE_AMR_WB      = 107,
} av_enc_type_t;

typedef enum _rc_mode_t
{
    RC_MODE_CBR             = 0,
    RC_MODE_VBR             = 1,
    RC_MODE_CQP             = 2,
    RC_MODE_ABR             = 3,

    RC_MODE_CRF             = 5,    // for 'X264_RC_CRF'
} rc_mode_t;

typedef enum _av_mux_type_t
{
    AV_MUX_TYPE_NONE        = -1,
    AV_MUX_TYPE_MP4         = 0,
    AV_MUX_TYPE_MPEG_TS     = 1,
} av_mux_type_t;

typedef enum _stream_index_e
{
    STREAM_INDEX_NONE       = -1,
    STREAM_INDEX_AUDIO      = 0,
    STREAM_INDEX_VIDEO      = 1,
} stream_index_e;

typedef enum _disp_dev_e
{
    DISPLAY_DEVICE_NONE     = -1,
    DISPLAY_DEVICE_HDMI     = 0,
    DISPLAY_DEVICE_LCD      = 1,
} disp_dev_e;

typedef enum _audio_device_e
{
    AUDIO_DEVICE_NONE       = -1,
    AUDIO_DEVICE_CODEC      = 0,
    AUDIO_DEVICE_HDMI       = 1,
} audio_device_e;

typedef enum
{
    AUDIO_SAMPLE_RATE_8K    = 8000,
    AUDIO_SAMPLE_RATE_16K   = 16000,
    AUDIO_SAMPLE_RATE_22K   = 22050,
    AUDIO_SAMPLE_RATE_32K   = 32000,
    AUDIO_SAMPLE_RATE_44K   = 44100,
    AUDIO_SAMPLE_RATE_48K   = 48000,
} audio_sample_e;

typedef enum
{
    AUDIO_BITS_8            = 8,
    AUDIO_BITS_16           = 16,
    AUDIO_BITS_24           = 24,
    AUDIO_BITS_32           = 32,
} audio_bits_e;

typedef enum
{
    AUDIO_CHANNEL_MONO      = 1,
    AUDIO_CHANNEL_STERO     = 2,
} audio_channel_e;

typedef enum
{
    ROTATE_DEGREE_NONE      = 0,
    ROTATE_DEGREE_0         = ROTATE_DEGREE_NONE,
    ROTATE_DEGREE_90,
    ROTATE_DEGREE_180,
    ROTATE_DEGREE_270,
} rotate_degree_e;

typedef struct _yuv_frame_t
{
    unsigned int        phy_addr[3];
    uint8_t *           vir_addr[3];
    unsigned int        stride[3];
} yuv_frame_t;

typedef struct _es_frame_t
{
    unsigned int        unused[3];
    uint8_t *           es_data[3];
    unsigned int        es_size[3];
} es_frame_t;

typedef struct _video_frame_t
{
    av_format_e         format;
    unsigned int        width;
    unsigned int        height;

    union vframe_u
    {
        yuv_frame_t     yuv;
        es_frame_t      es;
    } vframe;

    unsigned long long  pts;
} video_frame_t;

typedef struct _audio_frame_t
{
    av_format_e         format;
    uint8_t *           data;
    unsigned int        size;
    unsigned long long  pts;
} audio_frame_t;

/**
 * @Deprecated, suggest to use 'av_frame2_t'
 */
typedef struct _av_frame_t
{
    stream_index_e      av_index;

    union frame_u
    {
        video_frame_t * vframe;
        audio_frame_t * aframe;
    } frame;
} av_frame_t;

#define AV_NUM_PLANES 8
typedef struct _av_frame2_t
{
    stream_index_e      av_index;
    av_format_e         format;

    uint8_t *           data[AV_NUM_PLANES];
    unsigned long       data_phy[AV_NUM_PLANES];
    uint32_t            size[AV_NUM_PLANES];
    uint32_t            stride[AV_NUM_PLANES];

    /*
     * microsecond(us)
     */
    uint64_t            pts;

    /*
     * for video
     */
    uint32_t            width;
    uint32_t            height;

    /*
     * for audio
     */
    uint32_t            channels;
    uint32_t            sample_rate;
    uint32_t            bits;
    uint32_t            nb_samples;

    /*
     * 'p_priv' only used in framework tunnel mode
     */
    void *              p_priv;

    /*
     * for video crop
     */
    uint32_t            crop_x;
    uint32_t            crop_y;
    uint32_t            crop_w;
    uint32_t            crop_h;

    /*
     * frame id for frame management
     */
    uint32_t            id;

    uint32_t            reserved[4];
} av_frame2_t;

/*
 * mpp source callback function.
 * mpp source notity the video es, raw yuv, or audio es, pcm to the app.
 */
typedef int (* mpp_data_cb)(void * user, void * p_frame);
typedef int (* mpp_data_cb2)(void * user, void * p_frame, void * ext1, void * ext2);

typedef struct _mpp_source_callback_t
{
    mpp_data_cb cb;
    void * user;
} mppsource_callback_t, vsource_callback_t, asource_callback_t;

#ifdef __cplusplus
}
#endif

#endif  // __LIND_COMPONENT_H__

